package org.despair2D 
{
	import flash.utils.Dictionary;
	
	/**
	 * @usage
	 * 
	 * [method]
	 *			1. ◆addListener
	 * 			2. ◆removeListener
	 * 			3. ◆execute
	 * 			4. ◆dispose
	 */
final public class Observer
{
	
	/**
	 * 加入侦听器
	 * @param	listener
	 * @param	priority
	 */
	final public function addListener( listener:Function, priority:int = 0 ) : void
	{
		var lo:ListenerObject, tmpLo:ListenerObject;
		
		if (!m_listenerList)
		{
			m_listenerList = new Dictionary()
		}
		
		else if (m_listenerList[listener])
		{
			this.removeListener(listener)
		}
		
		lo                        =  new ListenerObject
		lo.listener               =  listener
		lo.priority               =  priority
		m_listenerList[listener]  =  lo
		
		// 没有
		if (m_length++ == 0)
		{
			m_head = lo
			return
		}
		
		// 最高
		if(priority > m_head.priority)
		{
			lo.next  =  m_head
			m_head   =  m_head.prev  =  lo
			return;
		}
		
		tmpLo = m_head;
		
		// 比较优先级，相同优先级按加入先后顺序执行.
		while (tmpLo.next && priority <= tmpLo.next.priority)
		{
			tmpLo = tmpLo.next
		}
		
		// 插入后面
		if (tmpLo.next)
		{
			lo.next     =  tmpLo.next
			lo.prev     =  tmpLo
			tmpLo.next  =  tmpLo.next.prev  =  lo
		}
		
		// 末尾
		else
		{
			lo.prev     =  tmpLo
			tmpLo.next  =  lo
		}
	}
	
	/**
	 * 移除侦听器
	 * @param	listener
	 * @return  true : 正常。 false : 已没有侦听器 (自动回收)
	 */
	final public function removeListener( listener:Function ) : Boolean
	{
		var lo:ListenerObject = m_listenerList[listener]
		delete m_listenerList[listener]
		
		// 自动回收
		if (--m_length == 0)
		{
			lo.dispose();
			m_head = null;
			return false;
		}
		
		if (lo.prev)
		{
			lo.prev.next = lo.next;
		}
		
		else
		{
			m_head = lo.next;
		}
		
		if (lo.next)
		{
			lo.next.prev = lo.prev;
		}

		lo.dispose();
		return true;
	}
	
	/**
	 * 执行
	 */
	final public function execute() : void
	{
		var lo:ListenerObject
		
		lo = m_head
		while (lo)
		{
			lo.listener();
			lo = lo.next;
		}
	}
	
	/**
	 * 释放
	 */
	final public function dispose() : void
	{
		var item:*;
		
		if (m_length)
		{
			for (item in m_listenerList)
			{
				m_listenerList[item].dispose();
				delete m_listenerList[item];
			}
			
			m_listenerList  =  null
			m_head          =  null;
		}
	}
	
	
	private var m_listenerList:Dictionary;  // listener : listenerObject
	
	private var m_head:ListenerObject;
	
	private var m_length:int;
}
}

final class ListenerObject 
{
	
	final internal function dispose():void
	{
		prev = next = null;
		listener = null;
	}
	
	
	internal var prev:ListenerObject, next:ListenerObject;
	
	internal var listener:Function
	
	internal var priority:int;
}